"""编码解码"""
import asyncio
from  struct import pack, unpack

from umq.errors import NoDataException


def bytes_to_hex_str(data):
    pass


async def read_or_raise(reader, n=-1):
    """
    读取n个字节的数据，如果读不到数据则抛出 NoDataException 异常
    :reader: StreamReaderAdapter对象实例
    :n: 需要读取的数据
    :return: 读到的字节
    """
    data = await reader.read(n)
    if not data:
        raise NoDataException('No data')
    return data

async def decode_string(reader) -> str:
    """
    读取一个字符串并解码，按照mqtt的协议读取
    :return: utf-8 string
    """
    length_byte = await read_or_raise(reader, 2)
    str_length = unpack('!H', length_byte)
    if str_length[0]:
        byte_str = await read_or_raise(reader, str_length[0])
        try:
            return byte_str.decode(encoding='utf-8')
        except:
            return str(byte_str)
    else:
        return ''

async def decode_data_with_length(reader) -> bytes:
    """
    从reader中读取一个固定2个字节长度的数据
    """
    length_byte = await read_or_raise(reader, 2)
    bytes_length = unpack('!H', length_byte)
    data = await read_or_raise(reader, bytes_length[0])
    return data

def bytes_to_int(data):
    """
    byte 转 int 用大端转
    :return: int
    """
    try:
        return int.from_bytes(data, byteorder='big')
    except:
        return data

async def decode_packet_id(reader) -> int:
    """读取解析packet_id"""
    packet_id_bytes = await read_or_raise(reader, 2)
    packet_id = unpack('!H', packet_id_bytes)
    return packet_id[0]

def int_to_bytes(int_value: int, length: int) -> bytes:
    if length == 1:
        fmt = '!B'
    elif length == 2:
        fmt = '!H'

    return pack(fmt, int_value)

def encode_string(string: str) -> bytes:
    data = string.encode('utf-8')
    data_length = len(data)
    return int_to_bytes(data_length, 2) + data
